// document http://wiki.synchro.net/ref:zmodem
namespace zmodem {
	const uint8_t SOH = 0x01;
	const uint8_t STX = 0x02;
	const uint8_t EOT = 0x04;
	const uint8_t ENQ = 0x05;
	const uint8_t ACK = 0x06;
	const uint8_t LF = 0x0a;
	const uint8_t CR = 0x0d;
	const uint8_t XON = 0x11;
	const uint8_t XOFF = 0x13;
	const uint8_t NAK = 0x15;
	const uint8_t CAN = 0x18;

	// ZMODEM
	const uint8_t ZPAD = 0x2a;		/* pad character; begins frames */
	const uint8_t ZDLE = 0x18;		/* ctrl-x zmodem escape */
	const uint8_t ZDLEE	 = 0x58;	/* escaped ZDLE */

	const uint8_t ZBIN = 0x41;		/* binary frame indicator (CRC16) */
	const uint8_t ZHEX = 0x42;		/* hex frame indicator */
	const uint8_t ZBIN32 = 0x43;	/* binary frame indicator (CRC32) */
	const uint8_t ZBINR32 = 0x44;	/* run length encoded binary frame (CRC32) */

	const uint8_t ZVBIN = 0x61;		/* binary frame indicator (CRC16) */
	const uint8_t ZVHEX = 0x62;		/* hex frame indicator */
	const uint8_t ZVBIN32 = 0x63;	/* binary frame indicator (CRC32) */
	const uint8_t ZVBINR32 = 0x64;	/* run length encoded binary frame (CRC32) */
	const uint8_t ZRESC = 0x7e;		/* run length encoding flag / escape character */

	// FRAME TYPES
	enum frame_type : uint8_t {
		ZRQINIT = 0x00,		/* request receive init (s->r) */
		ZRINIT = 0x01,		/* receive init (r->s) */
		ZSINIT = 0x02,		/* send init sequence (optional) (s->r) */
		ZACK = 0x03,		/* ack to ZRQINIT ZRINIT or ZSINIT (s<->r) */
		ZFILE = 0x04,		/* file name (s->r) */
		ZSKIP = 0x05,		/* skip this file (r->s) */
		ZNAK = 0x06,		/* last packet was corrupted (?) */
		ZABORT = 0x07,		/* abort batch transfers (?) */
		ZFIN = 0x08,		/* finish session (s<->r) */
		ZRPOS = 0x09,		/* resume data transmission here (r->s) */
		ZDATA = 0x0a,		/* data packet(s) follow (s->r) */
		ZEOF = 0x0b,		/* end of file reached (s->r) */
		ZFERR = 0x0c,		/* fatal read or write error detected (?) */
		ZCRC = 0x0d,		/* request for file CRC and response (?) */
		ZCHALLENGE = 0x0e,	/* security challenge (r->s) */
		ZCOMPL = 0x0f,		/* request is complete (?) */
		ZCAN = 0x10,		/* pseudo frame; other end cancelled session with 5* CAN */
		ZFREECNT = 0x11,	/* request free bytes on file system (s->r) */
		ZCOMMAND = 0x12,	/* issue command (s->r) */
		ZSTDERR = 0x13,		/* output data to stderr (??) */
	};
	// ZDLE SEQUENCES
	const uint8_t ZCRCE = 0x68;		/* CRC next, frame ends, header packet follows */
	const uint8_t ZCRCG = 0x69;		/* CRC next, frame continues nonstop */
	const uint8_t ZCRCQ = 0x6a;		/* CRC next, frame continuous, ZACK expected */
	const uint8_t ZCRCW = 0x6b;		/* CRC next, ZACK expected, end of frame */
	const uint8_t ZRUB0 = 0x6c;		/* translate to rubout 0x7f */
	const uint8_t ZRUB1 = 0x6d;		/* translate to rubout 0xff */

	// RECEIVER CAPABILITY FLAGS
	enum recv_cap {
		CANFDX = 0x01,	/* Rx can send and receive true full duplex */
		CANOVIO = 0x02,	/* Rx can receive data during disk I/O */
		CANBRK = 0x04,	/* Rx can send a break signal */
		CANCRY = 0x08,	/* Receiver can decrypt */
		CANLZW = 0x10,	/* Receiver can uncompress */
		CANFC32 = 0x20,	/* Receiver can use 32 bit Frame Check */
		ESCCTL = 0x40,	/* Receiver expects ctl chars to be escaped */
		ESC8 = 0x80,	/* Receiver expects 8th bit to be escaped */
	};
}